<script setup lang="ts">
import {
  nextTick,
  onBeforeUnmount,
  onMounted,
  ref,
  watch,
  computed,
  type ComponentPublicInstance
} from 'vue';
import { Plus, Delete, Edit, Lock } from '@element-plus/icons-vue';
import type { TabPaneName } from 'element-plus';
import { ElMessage } from 'element-plus';
import { useI18n } from 'vue-i18n';
import { changeLocale, getCurrentLocale } from '@renderer/i18n';

type TabItem = {
  title: string;
  name: string;
};

type Bounds = {
  x: number;
  y: number;
  width: number;
  height: number;
};

const { t, locale } = useI18n();

const currentLocale = ref<'zh' | 'en'>(getCurrentLocale() as 'zh' | 'en');

const languageOptions = computed(() => [
  { value: 'zh' as const, label: t('HOME_LANGUAGE_ZH') },
  { value: 'en' as const, label: t('HOME_LANGUAGE_EN') }
]);

const currentLanguageLabel = computed(() => {
  return languageOptions.value.find((option) => option.value === currentLocale.value)?.label ?? '';
});

const handleLanguageChange = (locale: 'zh' | 'en') => {
  changeLocale(locale);
  currentLocale.value = locale;
};

watch(
  () => locale.value,
  (newLocale) => {
    if (newLocale === currentLocale.value) {
      return;
    }
    currentLocale.value = newLocale as 'zh' | 'en';
  },
  { immediate: true }
);

let tabIndex = 1;
const editableTabsValue = ref('1');
const editableTabs = ref<TabItem[]>([
  {
    title: t('HOME_NEW_TAB'),
    name: '1'
  }
]);

// tab的连接状态
type TabConnectionInfo = {
  connectionId?: string;
  sessionId?: string;
  webSessionId?: string;
  baseUrl?: string;
  csrfToken?: string;
  cookie?: { name: string; value: string };
};

// 保存的连接信息
type SavedConnection = {
  id: string;
  ip: string;
  port: number;
  label: string;
};

type TabCloseResult = {
  shouldClose?: boolean;
  saveInfo?: { ip: string; port: number };
};

const tabConnections = new Map<string, TabConnectionInfo>();
const pendingTabQueries = new Map<string, Record<string, string>>();
const savedConnections = ref<SavedConnection[]>([]);

// 从localStorage加载保存的连接
const loadSavedConnections = () => {
  try {
    const saved = localStorage.getItem('saved-connections');
    if (saved) {
      savedConnections.value = JSON.parse(saved);
    }
  } catch (e) {
    console.error('Failed to load saved connections:', e);
  }
};

// 保存连接到localStorage
const saveConnectionsToStorage = () => {
  try {
    localStorage.setItem('saved-connections', JSON.stringify(savedConnections.value));
  } catch (e) {
    console.error('Failed to save connections:', e);
  }
};

// 从baseUrl提取IP和端口
const parseConnectionInfo = (baseUrl: string): { ip: string; port: number } | null => {
  try {
    const url = new URL(baseUrl);
    const ip = url.hostname;
    const port = parseInt(url.port) ?? 443;
    return { ip, port };
  } catch (e) {
    console.error('Failed to parse connection info:', e);
    return null;
  }
};

// 添加保存的连接
const addSavedConnection = (ip: string, port: number) => {
  const exists = savedConnections.value.some((conn) => conn.ip === ip && conn.port === port);
  if (exists) {
    return false;
  }

  const newConnection: SavedConnection = {
    id: Date.now().toString(),
    ip,
    port,
    label: `${ip}:${port}`
  };
  savedConnections.value.push(newConnection);
  saveConnectionsToStorage();
  return true;
};

const logoutWebSession = async (info: TabConnectionInfo | undefined, trigger: string) => {
  if (!info) {
    return;
  }
  const sessionId = info.webSessionId;
  const baseUrl = info.baseUrl;
  const csrfToken = info.csrfToken;
  const cookie = info.cookie;
  if (!sessionId || !baseUrl || !csrfToken || !cookie?.name || !cookie?.value) {
    console.warn(`skip web logout: missing info, trigger=${trigger}`);
    return;
  }
  const logoutUrl = `${baseUrl}/UI/Rest/Sessions/${sessionId}`;
  try {
    await window.api?.fetchData?.({
      method: 'delete',
      url: logoutUrl,
      headers: {
        From: 'WebUI',
        'X-CSRF-Token': csrfToken,
        cookie: `${cookie.name}=${cookie.value}`
      }
    });
  } catch (error) {
    console.error(`web session logout failed, trigger=${trigger}`, error);
  }
};

// 删除KVM会话
const deleteKvmUser = async (info: TabConnectionInfo | undefined, trigger: string) => {
  if (!info) {
    return;
  }
  const sessionId = info.sessionId;
  const baseUrl = info.baseUrl;
  const csrfToken = info.csrfToken;
  const cookie = info.cookie;
  if (!sessionId || !baseUrl || !csrfToken || !cookie?.name || !cookie?.value) {
    return;
  }
  const logoutUrl = `${baseUrl}/UI/Rest/Sessions/${sessionId}`;
  try {
    await window.api?.fetchData?.({
      method: 'delete',
      url: logoutUrl,
      headers: {
        From: 'WebUI',
        'X-CSRF-Token': csrfToken,
        cookie: `${cookie.name}=${cookie.value}`
      }
    });
  } catch (error) {}
};

// 清理所有连接
const cleanupAllConnections = async (trigger: string) => {
  // 清理所有WebSocket连接和会话
  const cleanupPromises: Promise<void>[] = [];

  for (const [tabId, connectionInfo] of tabConnections.entries()) {
    // 断开WebSocket连接
    if (connectionInfo.connectionId) {
      cleanupPromises.push(
        window.api?.websocket
          ?.disconnect?.(connectionInfo.connectionId)
          .then(() => {
            console.log(`WebSocket 断开成功: ${connectionInfo.connectionId}`);
          })
          .catch((error) => {
            console.error(`WebSocket 断开失败: ${connectionInfo.connectionId}`, error);
          })
      );
    }

    // 删除KVM会话
    if (connectionInfo.sessionId) {
      cleanupPromises.push(deleteKvmUser(connectionInfo, `${trigger}-kvm-${tabId}`));
    }

    // 退出Web会话
    if (connectionInfo.webSessionId) {
      cleanupPromises.push(logoutWebSession(connectionInfo, `${trigger}-web-${tabId}`));
    }
  }

  await Promise.all(cleanupPromises);
  tabConnections.clear();
};

// 编辑弹窗
const openEditDialog = async (connection: SavedConnection) => {
  if (!window.api?.dialog?.showEditConnection) {
    ElMessage.error(t('HOME_EDIT_DIALOG_ERROR'));
    return;
  }

  try {
    const result = await window.api.dialog.showEditConnection({
      id: connection.id,
      ip: connection.ip,
      port: connection.port,
      label: connection.label
    });
    if (!result?.success) {
      ElMessage.error(t('HOME_EDIT_DIALOG_ERROR'));
    }
  } catch (error) {
    ElMessage.error(t('HOME_EDIT_DIALOG_ERROR'));
  }
};

// 删除弹窗
const openDeleteDialog = async (connection: SavedConnection) => {
  if (!window.api?.dialog?.showDeleteConnection) {
    ElMessage.error(t('HOME_DELETE_DIALOG_ERROR') || '打开删除对话框失败');
    return;
  }

  try {
    const result = await window.api.dialog.showDeleteConnection({
      id: connection.id,
      ip: connection.ip,
      port: connection.port,
      label: connection.label
    });

    if (!result?.success) {
      ElMessage.error(t('HOME_DELETE_DIALOG_ERROR') || '打开删除对话框失败');
    }
  } catch (error) {
    ElMessage.error(t('HOME_DELETE_DIALOG_ERROR') || '打开删除对话框失败');
  }
};

// 查找相同IP和端口的连接
const findExistingConnection = (ip: string, port: number): string | null => {
  for (const [tabId, connectionInfo] of tabConnections.entries()) {
    if (connectionInfo.baseUrl) {
      const parsed = parseConnectionInfo(connectionInfo.baseUrl);
      if (parsed && parsed.ip === ip && parsed.port === port) {
        return tabId;
      }
    }
  }
  for (const [tabId, query] of pendingTabQueries.entries()) {
    if (query.ip === ip && query.port === port.toString()) {
      return tabId;
    }
  }
  return null;
};

const connectToSaved = (connection: SavedConnection) => {
  const existingTabId = findExistingConnection(connection.ip, connection.port);
  if (existingTabId) {
    ElMessage({
      message: t('LOGIN_EXISTING_CONNECTION', { ip: connection.ip, port: connection.port }),
      type: 'info'
    });
    editableTabsValue.value = existingTabId;
    nextTick(() => {
      void activateTabView(existingTabId);
    });
    return;
  }

  const newTabName = `${++tabIndex}`;
  editableTabs.value.push({
    title: t('HOME_NEW_TAB'),
    name: newTabName
  });
  editableTabsValue.value = newTabName;
  pendingTabQueries.set(newTabName, {
    ip: connection.ip,
    port: connection.port.toString()
  });
  nextTick(() => {
    void activateTabView(newTabName);
  });
};

// 初始化时加载保存的连接
loadSavedConnections();

// 设置tab的连接信息
const setTabConnectionInfo = (tabId: string, info: TabConnectionInfo) => {
  tabConnections.set(tabId, info);
};

// 获取tab的连接信息
const getTabConnectionInfo = (tabId: string): TabConnectionInfo | undefined => {
  return tabConnections.get(tabId);
};

// 更新tab的title
const updateTabTitle = (tabId: string, title: string) => {
  const tab = editableTabs.value.find((t) => t.name === tabId);
  if (tab) {
    tab.title = title;
  }
};

// 激活已存在的tab
const activateExistingTab = (tabId: string) => {
  editableTabsValue.value = tabId;
  nextTick(() => {
    void activateTabView(tabId);
  });
};

// 清理tab的连接信息
const clearTabConnectionInfo = (tabId: string) => {
  if (tabId) {
    tabConnections.delete(tabId);
    pendingTabQueries.delete(tabId);
  }
};

(window as any).setTabConnectionInfo = setTabConnectionInfo;
(window as any).getTabConnectionInfo = getTabConnectionInfo;
(window as any).findExistingConnection = findExistingConnection;
(window as any).activateExistingTab = activateExistingTab;
(window as any).clearTabConnectionInfo = clearTabConnectionInfo;

const tabContainers = new Map<string, HTMLElement>();
const createdTabs = new Set<string>();
const resizeObservers = new Map<string, ResizeObserver>();
const ipcSubscriptions: Array<() => void> = [];

const getTabViewApi = () => window.api?.tabView;

const toBounds = (element: HTMLElement | undefined | null): Bounds | null => {
  if (!element) {
    return null;
  }
  const rect = element.getBoundingClientRect();
  if (rect.width <= 0 || rect.height <= 0) {
    return null;
  }
  return {
    x: Math.round(rect.left),
    y: Math.round(rect.top),
    width: Math.round(rect.width),
    height: Math.round(rect.height)
  };
};

const resolveElement = (target: Element | ComponentPublicInstance | null): HTMLElement | null => {
  if (!target) {
    return null;
  }
  if (target instanceof HTMLElement) {
    return target;
  }
  const candidate = (target as ComponentPublicInstance & { $el?: Element }).$el;
  return candidate instanceof HTMLElement ? candidate : null;
};

const registerContainer = (tabId: string, el: Element | ComponentPublicInstance | null) => {
  if (!el) {
    tabContainers.delete(tabId);
    detachResizeObserver(tabId);
    return;
  }
  const element = resolveElement(el);
  if (!element) {
    return;
  }
  tabContainers.set(tabId, element);
  attachResizeObserver(tabId, element);
  nextTick(() => {
    if (editableTabsValue.value === tabId) {
      void activateTabView(tabId);
    } else {
      void ensureTabView(tabId);
    }
  });
};

const ensureTabView = async (tabId: string): Promise<void> => {
  if (createdTabs.has(tabId)) {
    return;
  }
  const tabViewApi = getTabViewApi();
  if (!tabViewApi) {
    return;
  }
  const bounds = toBounds(tabContainers.get(tabId));
  if (!bounds) {
    return;
  }
  const initialQuery = pendingTabQueries.get(tabId);
  await tabViewApi.create(tabId, bounds, initialQuery ? { query: initialQuery } : undefined);
  if (initialQuery) {
    pendingTabQueries.delete(tabId);
  }
  createdTabs.add(tabId);
};

const activateTabView = async (tabId: string): Promise<void> => {
  const tabViewApi = getTabViewApi();
  if (!tabViewApi) {
    return;
  }
  await ensureTabView(tabId);
  const bounds = toBounds(tabContainers.get(tabId));
  if (!bounds) {
    return;
  }
  await tabViewApi.activate(tabId, bounds);
};

const resizeTabView = async (tabId: string): Promise<void> => {
  const tabViewApi = getTabViewApi();
  if (!tabViewApi || !createdTabs.has(tabId)) {
    return;
  }
  const bounds = toBounds(tabContainers.get(tabId));
  if (!bounds) {
    return;
  }
  await tabViewApi.resize(tabId, bounds);
};

const cleanupTabResources = (tabId: TabPaneName | undefined): void => {
  if (tabId === undefined || tabId === null) {
    return;
  }
  const normalizedId = String(tabId);
  const tabViewApi = getTabViewApi();
  tabViewApi?.destroy(normalizedId);
  createdTabs.delete(normalizedId);
  detachResizeObserver(normalizedId);
  tabContainers.delete(normalizedId);
};

const attachResizeObserver = (tabId: string, element: HTMLElement) => {
  if (resizeObservers.has(tabId)) {
    return;
  }
  const observer = new ResizeObserver(() => {
    if (editableTabsValue.value === tabId) {
      void resizeTabView(tabId);
    }
  });
  observer.observe(element);
  resizeObservers.set(tabId, observer);
};

const detachResizeObserver = (tabId: string) => {
  const observer = resizeObservers.get(tabId);
  if (observer) {
    observer.disconnect();
    resizeObservers.delete(tabId);
  }
};

const handleWindowResize = () => {
  void resizeTabView(editableTabsValue.value);
};

window.addEventListener('resize', handleWindowResize);

const handleTabsEdit = async (targetName: TabPaneName | undefined, action: 'remove' | 'add') => {
  if (action === 'add') {
    const newTabName = `${++tabIndex}`;
    editableTabs.value.push({
      title: t('HOME_NEW_TAB'),
      name: newTabName
    });
    editableTabsValue.value = newTabName;
    nextTick(() => {
      void activateTabView(newTabName);
    });
    return;
  }
  if (action === 'remove' && targetName) {
    const tabs = editableTabs.value;
    let activeName = editableTabsValue.value;

    const tabIdStr = String(targetName);

    if (activeName !== targetName) {
      editableTabsValue.value = String(targetName);
      activeName = String(targetName);
      await nextTick();
      await activateTabView(tabIdStr);
    }

    const connectionInfo = tabConnections.get(tabIdStr);
    const hasConnection = connectionInfo && connectionInfo.connectionId;

    let saveInfoFromView: TabCloseResult['saveInfo'];
    if (hasConnection && window.api?.tabView?.requestClose) {
      try {
        const closeResult = (await window.api.tabView.requestClose(tabIdStr)) as TabCloseResult;
        if (closeResult?.shouldClose === false) {
          return;
        }
        if (closeResult?.saveInfo) {
          saveInfoFromView = closeResult.saveInfo;
        }
      } catch (error) {
        console.warn(`Failed to request close confirmation for tab ${tabIdStr}:`, error);
      }
    }
    if (saveInfoFromView) {
      const saved = addSavedConnection(saveInfoFromView.ip, saveInfoFromView.port);
      if (!saved) {
        ElMessage({
          message: t('HOME_CONNECTION_EXISTS'),
          type: 'warning'
        });
      }
    }

    // 关闭tab前断开websocket和退出会话
    if (connectionInfo?.connectionId) {
      try {
        await window.api?.websocket?.disconnect?.(connectionInfo.connectionId);
      } catch (error) {
        console.error(`Failed to disconnect WebSocket for tab ${targetName}:`, error);
      }
    }
    // 同时退出KVM会话和Web会话
    const logoutPromises: Promise<void>[] = [];
    if (connectionInfo?.sessionId) {
      logoutPromises.push(deleteKvmUser(connectionInfo, `tab-close-kvm-${tabIdStr}`));
    }
    if (connectionInfo?.webSessionId) {
      logoutPromises.push(logoutWebSession(connectionInfo, `tab-close-web-${tabIdStr}`));
    }
    await Promise.all(logoutPromises);

    if (activeName === targetName) {
      tabs.forEach((tab, index) => {
        if (tab.name === targetName) {
          const nextTab = tabs[index + 1] || tabs[index - 1];
          if (nextTab) {
            activeName = nextTab.name;
          }
        }
      });
    }
    cleanupTabResources(targetName);
    tabConnections.delete(String(targetName));
    editableTabsValue.value = activeName;
    editableTabs.value = tabs.filter((tab) => tab.name !== targetName);
  }
};

watch(
  () => editableTabsValue.value,
  (tabId) => {
    if (!tabId) {
      return;
    }
    nextTick(() => {
      void activateTabView(tabId);
    });
  },
  { immediate: true }
);

watch(
  () => currentLocale.value,
  () => {
    editableTabs.value.forEach((tab) => {
      const oldZhTitle = '新标签页';
      const oldEnTitle = 'New Tab';
      if (tab.title === oldZhTitle || tab.title === oldEnTitle || tab.title === 'new tab') {
        tab.title = t('HOME_NEW_TAB');
      }
    });
  }
);

// 打开信任站点列表窗口
const openTrustedSitesListDialog = async () => {
  try {
    const result = await window.api.dialog.showTrustedSitesList();
    if (!result.success) {
      ElMessage.error(result.error || t('HOME_TRUST_LIST_OPEN_FAILED'));
    }
  } catch (error) {
    ElMessage.error(t('HOME_TRUST_LIST_OPEN_FAILED'));
  }
};

// 打开帮助窗口
const openHelpWindow = async () => {
  try {
    const result = await window.api?.dialog?.showHelp?.();
    if (!result || !result.success) {
      ElMessage.error('打开帮助窗口失败');
    }
  } catch (error) {
    ElMessage.error('打开帮助窗口失败');
  }
};

onMounted(() => {
  const ipc = window.api?.ipc;
  if (!ipc) {
    return;
  }
  ipcSubscriptions.push(
    ipc.on('tab-title-updated', (data: { tabId: string; title: string }) => {
      updateTabTitle(data.tabId, data.title);
    })
  );
  ipcSubscriptions.push(
    ipc.on(
      'tab-conn-info',
      (data: {
        tabId: string;
        connectionId?: string;
        sessionId?: string;
        webSessionId?: string;
        baseUrl?: string;
        csrfToken?: string;
        cookie?: { name: string; value: string };
        clear?: boolean;
      }) => {
        if (data?.tabId) {
          if (data.clear) {
            tabConnections.delete(data.tabId);
            pendingTabQueries.delete(data.tabId);
            return;
          }
          tabConnections.set(data.tabId, {
            connectionId: data.connectionId,
            sessionId: data.sessionId,
            webSessionId: data.webSessionId,
            baseUrl: data.baseUrl,
            csrfToken: data.csrfToken,
            cookie: data.cookie
          });
        }
      }
    )
  );
  ipcSubscriptions.push(
    ipc.on(
      'duplicate-connection-activated',
      (payload: { ip: string; port: number; tabId?: string }) => {
        if (!payload?.ip || !payload?.port) {
          return;
        }
        ElMessage({
          message: t('LOGIN_EXISTING_CONNECTION', { ip: payload.ip, port: payload.port }),
          type: 'info',
          duration: 5000
        });
      }
    )
  );

  // 监听应用关闭事件，清理所有连接
  if (window.api?.app?.onWillQuit) {
    window.api.app.onWillQuit(() => {
      cleanupAllConnections('app-will-quit');
    });
  }
  // 编辑保存
  ipcSubscriptions.push(
    ipc.on(
      'edit-connection-saved',
      (payload: { connectionId?: string; data?: SavedConnection }) => {
        if (!payload?.data) {
          return;
        }
        handleEditConnectionSaved(payload.data);
      }
    )
  );
  // 删除确认
  ipcSubscriptions.push(
    ipc.on(
      'delete-connection-confirmed',
      (payload: { connectionId?: string; data?: SavedConnection }) => {
        if (!payload?.data) {
          return;
        }
        handleDeleteConnectionConfirmed(payload.data);
      }
    )
  );
});

// 处理删除确认
const handleDeleteConnectionConfirmed = async (data: SavedConnection) => {
  if (!data) return;

  try {
    const index = savedConnections.value.findIndex((conn) => conn.id === data.id);
    if (index > -1) {
      savedConnections.value.splice(index, 1);
      saveConnectionsToStorage();
      ElMessage.success(t('HOME_CONNECTION_DELETE_SUCCESS'));
    } else {
      ElMessage.error(t('HOME_CONNECTION_DELETE_FAILED'));
    }
  } catch (error) {
    ElMessage.error(t('HOME_CONNECTION_DELETE_FAILED'));
  }
};

// 处理编辑保存
const handleEditConnectionSaved = async (data: SavedConnection) => {
  try {
    const index = savedConnections.value.findIndex((conn) => conn.id === data.id);
    if (index > -1) {
      const duplicateLabel = savedConnections.value.some(
        (conn, idx) => idx !== index && conn.label === data.label
      );
      if (duplicateLabel) {
        ElMessage.warning(t('HOME_CONNECTION_EXISTS'));
        return;
      }

      // 检查新的IP和端口组合是否与其他连接冲突
      const duplicateConnection = savedConnections.value.some(
        (conn, idx) => idx !== index && conn.ip === data.ip && conn.port === data.port
      );
      if (duplicateConnection) {
        ElMessage.warning(
          t('HOME_DUPLICATE_CONNECTION', { ip: data.ip, port: data.port }) ||
            `已存在相同IP和端口的连接: ${data.ip}:${data.port}`
        );
        return;
      }

      // 更新连接信息
      savedConnections.value[index].label = data.label;
      savedConnections.value[index].ip = data.ip;
      savedConnections.value[index].port = data.port;
      saveConnectionsToStorage();
      ElMessage.success(t('HOME_CONNECTION_EDIT_SUCCESS'));
    } else {
      ElMessage.error(t('HOME_CONNECTION_EDIT_FAILED'));
    }
  } catch (error) {
    ElMessage.error(t('HOME_CONNECTION_EDIT_FAILED'));
  }
};

onBeforeUnmount(() => {
  window.removeEventListener('resize', handleWindowResize);
  if (ipcSubscriptions.length > 0) {
    ipcSubscriptions.splice(0).forEach((unsubscribe) => unsubscribe());
  }
  window.api?.ipc?.removeAllListeners('tab-title-updated');
  window.api?.ipc?.removeAllListeners('tab-conn-info');
  window.api?.ipc?.removeAllListeners('duplicate-connection-activated');
  window.api?.ipc?.removeAllListeners('edit-connection-saved');
  window.api?.ipc?.removeAllListeners('delete-connection-confirmed');
  editableTabs.value.forEach((tab) => {
    cleanupTabResources(tab.name);
  });
});
</script>
<template>
  <div id="home-container">
    <el-container>
      <el-header class="header-container">
        <div class="header-content">
          <span class="header-title">Remote Virtual Console</span>
          <div class="header-actions">
            <button class="action-btn trust-btn" @click="openTrustedSitesListDialog">
              <el-icon>
                <Lock />
              </el-icon>
              <span>{{ t('HOME_TRUST_LIST') }}</span>
            </button>
            <span class="action-divider" />
            <el-dropdown trigger="hover" @command="handleLanguageChange">
              <button class="action-btn language-btn">
                <span class="icon-lang icon-language"></span>
                <span>{{ currentLanguageLabel }}</span>
              </button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item
                    v-for="option in languageOptions"
                    :key="option.value"
                    :command="option.value"
                    :class="{ active: currentLocale === option.value }"
                  >
                    {{ option.label }}
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
            <button class="action-btn icon-btn" type="button" @click="openHelpWindow">
              <span id="navHelp" class="icon-help"></span>
            </button>
          </div>
        </div>
      </el-header>
      <el-container class="container-box">
        <el-aside width="260px" class="aside-container">
          <div class="saved-connections">
            <div class="connections-header">
              <h3>{{ t('HOME_SAVED_CONNECTIONS') }}</h3>
            </div>
            <div v-if="savedConnections.length === 0" class="empty-connections">
              <p>{{ t('HOME_NO_SAVED_CONNECTIONS') }}</p>
            </div>
            <ul v-else class="connections-list">
              <li v-for="conn in savedConnections" :key="conn.id" class="connection-item">
                <div class="connection-content" @click="connectToSaved(conn)">
                  <div class="connection-info">
                    <div class="connection-label" :title="conn.label">{{ conn.label }}</div>
                    <div class="connection-address">
                      <div class="connection-ip">{{ conn.ip }}</div>
                      <div class="connection-port">{{ conn.port }}</div>
                    </div>
                  </div>
                </div>
                <div class="connection-actions">
                  <el-icon
                    class="edit-icon"
                    :title="$t('HOME_EDIT_CONNECTION')"
                    @click.stop="openEditDialog(conn)"
                  >
                    <Edit />
                  </el-icon>
                  <el-icon
                    class="delete-icon"
                    :title="$t('HOME_DELETE_CONNECTION')"
                    @click.stop="openDeleteDialog(conn)"
                  >
                    <Delete />
                  </el-icon>
                </div>
              </li>
            </ul>
          </div>
        </el-aside>
        <el-main class="main-container">
          <el-tabs
            v-model="editableTabsValue"
            type="card"
            class="my-tabs"
            editable
            @edit="handleTabsEdit"
          >
            <template #add-icon>
              <el-icon>
                <Plus />
              </el-icon>
            </template>
            <el-tab-pane
              v-for="item in editableTabs"
              :key="item.name"
              :label="item.title"
              :name="item.name"
            >
              <div
                :ref="(el) => registerContainer(item.name, el)"
                class="tab-view-container"
                :data-tab-id="item.name"
              />
            </el-tab-pane>
          </el-tabs>
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>
<style lang="scss" scoped>
#home-container {
  width: 100vw;
  height: 100vh;
  background: #ebeff6;
}

.header-container {
  height: 48px;
  line-height: 48px;
  color: #000;
  background: var(--o-bg-color-base);
  border-bottom: 1px solid #eee;
  border-top: 1px solid #eee;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
}

.header-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.header-title {
  font-size: 16px;
  font-weight: 600;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: 3px;
}

.action-divider {
  width: 1px;
  height: 18px;
  background-color: #dcdfe6;
}

.action-btn {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 0 10px;
  height: 30px;
  border: none;
  background: transparent;
  color: #4e5865;
  font-size: 14px;
  cursor: pointer;
  border-radius: 6px;

  .el-icon,
  .icon-lang {
    font-size: 16px;
  }

  &:hover {
    background-color: rgba(22, 119, 255, 0.08);
    color: #1677ff;

    .icon-language::before {
      color: #1677ff;
    }
  }

  &:active {
    transform: scale(0.98);
  }
}

.trust-btn {
  font-weight: 600;
}

.language-btn {
  min-width: 60px;
  justify-content: center;

  .icon-language::before {
    color: #4e5865;
  }
}

.icon-btn {
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background-color: transparent;
  color: #4e5865;
  cursor: pointer;
  transition: color 0.2s ease;

  .icon-help::before {
    color: #4e5865;
  }

  &:hover {
    background-color: rgba(22, 119, 255, 0.08);
    color: #1677ff;

    .icon-help::before {
      color: #1677ff;
    }
  }
}

.icon-btn .icon-help::before {
  font-size: 18px;
  line-height: 32px;
  display: inline-block;
}

.el-dropdown-menu .active {
  color: #1677ff;
  font-weight: 600;
}

:deep(.el-dropdown-menu__item) {
  height: 20px;
  line-height: 20px;
  padding: 0 6px;
}

.container-box {
  background: #ebeff6;
  height: calc(100vh - 50px);
}

.aside-container {
  background: #ebeff6;
  overflow-y: auto;
  overflow-x: hidden;
  display: flex;
  flex-direction: column;
  position: relative;
}

.saved-connections {
  display: flex;
  flex-direction: column;
  height: 100%;

  .connections-header {
    padding: 12px 16px 12px;
    margin-bottom: 0;

    h3 {
      margin: 0;
      font-size: 14px;
      font-weight: 600;
      color: #4e5865;
      letter-spacing: 0.3px;
    }
  }

  .empty-connections {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 20px;

    p {
      margin: 0;
      color: #909399;
      font-size: 13px;
      text-align: center;
    }
  }

  .connections-list {
    list-style: none;
    padding: 0 0 0 12px;
    margin: 0px;
    flex: 1;
    overflow-y: auto;

    .connection-item {
      display: flex;
      align-items: flex-start;
      justify-content: space-between;
      padding: 12px;
      margin-bottom: 6px;
      background: #fff;
      border: 1px solid #e4e7ed;
      border-radius: 6px;
      transition: all 0.2s ease;
      cursor: pointer;
      position: relative;
      box-shadow: 0 1px 3px rgba(64, 158, 255, 0.08);

      .connection-content {
        flex: 1;
        min-width: 0;
        padding-right: 6px;
        overflow: hidden;
      }

      .connection-info {
        display: flex;
        flex-direction: column;
        gap: 6px;
        min-width: 0;
      }

      .connection-label {
        font-size: 14px;
        font-weight: 600;
        color: #000;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        line-height: 1.5;
        margin-bottom: 6px;
      }

      .connection-address {
        display: flex;
        flex-direction: column;
        gap: 4px;
        font-size: 12px;
        color: #000;
        line-height: 1.4;
        overflow: hidden;
      }

      .connection-ip {
        font-weight: 500;
        color: #2e2e2e;
      }

      .connection-port {
        color: #2e2e2e;
      }

      .connection-actions {
        display: flex;
        justify-content: flex-start;
        gap: 4px;
        margin-left: 6px;
        align-self: flex-start;
      }

      .edit-icon {
        color: #a9b2bf;
        font-size: 16px;
        cursor: pointer;
        padding: 4px;
        border-radius: 4px;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 24px;
        height: 24px;
        flex-shrink: 0;
      }

      .delete-icon {
        color: #a9b2bf;
        font-size: 16px;
        cursor: pointer;
        padding: 4px;
        border-radius: 4px;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 24px;
        height: 24px;
        flex-shrink: 0;
      }
    }
  }
}

.saved-connections .connections-list::-webkit-scrollbar {
  width: 6px;
}

.saved-connections .connections-list::-webkit-scrollbar-track {
  background: transparent;
}

.saved-connections .connections-list::-webkit-scrollbar-thumb {
  background: #c0c4cc;
  border-radius: 3px;

  &:hover {
    background: #a8abb2;
  }
}

.aside-container::-webkit-scrollbar {
  width: 6px;
}

.aside-container::-webkit-scrollbar-track {
  background: transparent;
}

.aside-container::-webkit-scrollbar-thumb {
  background: #c0c4cc;
  border-radius: 3px;

  &:hover {
    background: #a8abb2;
  }
}

.my-tabs > .el-tabs__content {
  padding: 32px;
  color: #6b778c;
  font-size: 32px;
  font-weight: 600;
}

.tab-view-container {
  width: 100%;
  height: calc(100vh - 160px);
  background-color: #fff;
}
.main-container {
  padding: 20px;
}
</style>
